﻿///<copyright>
/// Copyright © 2009 Stephen Styrchak. All Rights Reserved.
///</copyright>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;

namespace Ferpect.ComponentModel
{
    public class Container : System.ComponentModel.Container
    {
        private IServiceProvider serviceProvider;

        public Container(IServiceProvider serviceProvider)
        {
            if (serviceProvider == null) throw new ArgumentNullException("serviceProvider");
            this.serviceProvider = serviceProvider;
        }

        protected override object GetService(Type serviceType)
        {
            object service = base.GetService(serviceType);
            if (service == null)
            {
                service = this.serviceProvider.GetService(serviceType);
            }
            return service;
        }
    }
}

#if !WINDOWS
namespace System.ComponentModel
{
    public class Container : IContainer
    {
        private List<IComponent> components;
        private Random random;
        private IServiceProvider serviceProvider;

        public Container()
            : this(null)
        {
        }

        public Container(IServiceProvider serviceProvider)
        {
            this.components = new List<IComponent>();
            this.random = new Random();
            this.serviceProvider = serviceProvider;
        }

        protected virtual object GetService(Type serviceType)
        {
            if (this.serviceProvider == null)
                return null;
            return this.serviceProvider.GetService(serviceType);
        }

        internal void ValidateName(IComponent component, string name)
        {
            if (component == null) throw new ArgumentNullException("component");

            foreach (IComponent containedComponent in this.components)
            {
                ISite site = containedComponent.Site;
                if (((site != null) && (site.Name != null)) && (string.Equals(site.Name, name, StringComparison.OrdinalIgnoreCase) && (site.Component != component)))
                {
                    throw new ArgumentException(String.Format("Duplicate component name '{0}'.", name));
                }
            }
        }

        #region IContainer Members

        public void Add(IComponent component, string name)
        {
            if (component == null) throw new ArgumentNullException("component");

            if (component.Site != null && Object.ReferenceEquals(component.Site.Container, this))
            {
                // This component is already in the container.
                return;
            }
            if (name != null)
            {
                this.ValidateName(component, name);
            }

            Site site = new Site(component, this, name);
            this.components.Add(component);
            component.Site = site;
        }

        public void Add(IComponent component)
        {
            this.Add(component, null);
        }

        public ComponentCollection Components
        {
            get { return null; }
        }

        public void Remove(IComponent component)
        {
            if (component == null) throw new ArgumentNullException("component");

            this.components.Remove(component);
            component.Site = null;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            //foreach (IComponent component in this.components.Values)
            //{
            //    component.Site = null;
            //}
            this.components.Clear();
        }

        #endregion

        #region Nested Types

        private class Site : ISite, IServiceProvider
        {
            // Fields
            private IComponent component;
            private Container container;
            private string name;

            // Methods
            internal Site(IComponent component, Container container, string name)
            {
                this.component = component;
                this.container = container;
                this.name = name;
            }

            public object GetService(Type service)
            {
                if (service != typeof(ISite))
                {
                    return this.container.GetService(service);
                }
                return this;
            }

            // Properties
            public IComponent Component
            {
                get
                {
                    return this.component;
                }
            }

            public IContainer Container
            {
                get
                {
                    return this.container;
                }
            }

            public bool DesignMode
            {
                get
                {
                    return false;
                }
            }

            public string Name
            {
                get
                {
                    return this.name;
                }
                set
                {
                    if (((value == null) || (this.name == null)) || !value.Equals(this.name))
                    {
                        this.container.ValidateName(this.component, value);
                        this.name = value;
                    }
                }
            }
        }

        #endregion
    }
}
#endif
